#!/bin/bash
set -eu


# =====================================================================
# This script is used to control the time-tracker of the Time++ gnome
# shell extension:
#        https://github.com/zagortenay333/timepp__gnome
#
# Once executed, the script will listen for when the workspace change
# and do something.
#
# The tracker is controled by supplying string arguments.
# An arg string is of the form:
#       "["default" ]tracker_id n1[, n2, n3,...]"
#
# If the string starts with the "default" keyword then:
#    -  the given tracker_id is gonna be the default id
#    -  no workspace numbers need to provided
#
# The tracker_id is either:
#    - the string "stop"
#    - a tracker_id specified in Time++ using the the "tracker_id:string"
#      todo.txt extension. (See README of Time++.)
#
# The n1, n2, ... numbers correspond to workspace numbers. They are
# 0-indexed.
#
# Examples:
#
# 1) tracker_control "stop 0" "default id1 2 3" "id2 1 4"
#    Means:
#      - If on workspace number 0     , stop the tracker.
#      - If on workspace number 2 or 3, start tracking tasks with id "id1".
#      - If on workspace number 1 or 4, start tracking tasks with id "id2".
#      - If on any other workspace    , start tracking tasks with id "id1".
#
# 2) tracker_control "id1 2 3"
#    Means:
#      - If on workspace number 2 or 3, start tracking tasks with id "id1".
#      - If on any other workspace    , stop tracking.
#
# 3) tracker_control "default id1"
#    Means:
#      - Always track tasks with id "id1".
#
# 4) tracker_control
#    Means:
#      - Stop tracking.
#  =====================================================================


# =====================================================================
# @@@ Constants
# =====================================================================
declare -A id_workspace_map

current_workspace=0

current_id=0

default_id="stop"

shell_version=$(gnome-shell --version | cut -d " " -f 3)

get_workspace_cmd="global.display.get_active_workspace_index()"

[[ $shell_version < "3.29" ]] &&
    get_workspace_cmd="global.screen.get_active_workspace_index()"


# =====================================================================
# @@@ Funcs
# =====================================================================
stop_tracking () {
    >/dev/null gdbus call                               \
        --session                                       \
        --dest org.gnome.Shell                          \
        --object-path /timepp/zagortenay333/TimeTracker \
        --method timepp.zagortenay333.TimeTracker.stop_all_tracking
}

start_tracking () {
    local id=$1

    stop_tracking

    >/dev/null gdbus call                               \
        --session                                       \
        --dest org.gnome.Shell                          \
        --object-path /timepp/zagortenay333/TimeTracker \
        --method timepp.zagortenay333.TimeTracker.start_tracking_by_id "$id"
}

on_workspace_changed () {
    local found_id=$default_id
    local it
    local workspace

    for it in "${!id_workspace_map[@]}"; do
        for workspace in ${id_workspace_map[$it]}; do
            [[ $workspace == "$current_workspace" ]] && found_id=$it && break 1
        done
    done

    [[ $found_id == "$current_id" ]] && return

    if [[ $found_id == "stop" ]]; then
        stop_tracking
    else
        start_tracking "$found_id"
    fi

    current_id=$found_id
}

check_workspace () {
    local workspace
    read -r -a workspace <<< "$(
        gdbus call                         \
            --session                      \
            --dest org.gnome.Shell         \
            --object-path /org/gnome/Shell \
            --method org.gnome.Shell.Eval  \
                "$get_workspace_cmd"
    )"

    # gdbus will return a string of the form "('bool', 'n')".
    # We need to extract n only.
    workspace=${workspace[1]}
    workspace=${workspace:1: -2}

    if [[ $workspace != "$current_workspace" ]]; then
        current_workspace=$workspace
        on_workspace_changed
    fi
}


# =====================================================================
# @@@ Parse args
# =====================================================================
[[ $# == 0 ]] && stop_tracking && exit

for it in "$@"; do
    read -r -a it <<< "$it"

    case ${it[0]} in
        "default")
            default_id=${it[1]}
            id_workspace_map[${it[1]}]="${it[*]:2}"
            ;;
        *)
            id_workspace_map[${it[0]}]="${it[*]:1}"
    esac
done


# =====================================================================
# @@@ Mainloop
# =====================================================================
trap "stop_tracking" INT TERM EXIT

while true; do
    check_workspace
    sleep 1
done
